#!/usr/bin/python
import cherrypy
import datetime
import time
import shutil
import json
import collections

from cherrypy.process.plugins import Daemonizer

from uploader.federation.settingmaster import *
from settings import Settings

import hashlib

import logging
logging.basicConfig(filename='log.log',level=logging.DEBUG)

from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates'))

from ts.auth import Auth

from uploader.federation.federation import *
from uploader.federation.cryptTEA2 import *

cherrypy.config.update(    {
        'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
        'tools.trailing_slash.on': False,
        'tools.sessions.on' : True,
        'tools.sessions.storage_type' : "file",
        'tools.sessions.storage_path' : "sessions",
        'tools.sessions.timeout' : 60,
    })

class TangoSettings(object):
    abutton = "<br><a class'btn' href='/auth'>Login</a><br>"
    def get_timestamp(self):
        future = datetime.datetime.now()
        return time.mktime(future.timetuple())

    @cherrypy.expose
    def index(self):
        raise cherrypy.HTTPRedirect("/auth/")

    def save_user_rules(self, avaliable_for_users, namets):
        w5 = open("data/rules_user_%s.tmp" % namets, 'w+')
        w5.write(avaliable_for_users)
        w5.close()
        w6 = open("current_data/rules_user.tmp", 'w+')
        w6.write(avaliable_for_users)
        w6.close()

    def read_user_rules(self):
        try:
            ci = open('current_data/rules_user.tmp', 'r')
            rules_user = ci.read()
            ci.close()
        except IOError:
            rules_user = "{'tables':[],'game_const':[],'dynamic_const':[]}"

        # ci = open('current_data/rules_user.tmp', 'r')
        # rules_user = ci.read()
        # ci.close()

        return rules_user


    def save_to_file(self, filename, data, mode='w'):
        w1 = open(filename, mode)
        w1.write(data)
        w1.close()


    def init_basic_files(self):
        try:
            r = open('current_data/last.tmp', 'r')
        except (IOError, IndexError) as e:
            shutil.copyfile('current_data/start.json', 'current_data/last.tmp')

        try:
            rul = open('current_data/rules_last.tmp', 'r')
        except IOError:
            shutil.copyfile('current_data/start_rules.json', 'current_data/rules_last.tmp')

        try:
            ci = open('current_data/clientid', 'r')
        except IOError:
            ci = open('current_data/clientid', 'w+')
            ci.write('1733:53659:0.0.3:ios:appstore')
            ci.close()

    @cherrypy.expose
    def save_avaliabe_ids(self, data=None):
        clientids = json.loads(data)
        result = []
        for clientid in clientids:
            result.append({"text":clientid['text']})
        json_result = json.dumps(result)

        self.save_to_file('current_data/avaliable_ids', json_result)
        return data

    @cherrypy.expose
    def load_avaliabe_ids(self):
        fl = open('current_data/avaliable_ids', 'r')
        data = fl.readlines()
        print(data)
        return data
        # clientids = json.loads(.read())
        # clientids = json.loads(clientids)
        # print(clientids)
        # return clientids

    @cherrypy.expose
    def logs(self): 
        with open('log.log', "r") as f:
            lines = f.readlines()[-100:]
            res = "<br>\n".join(lines)

        return res


    @cherrypy.expose
    def editor(self, data=None, clientid=None, rules=None, clear_data=None, description=None, avaliable_for_users=None, save_to_svn=None):

        auth = Auth(cherrypy.session)
        if auth.is_auth() == False:
            return self.abutton

        self.init_basic_files()

        desc = ''
        if data and clear_data:
            print('Data here')
            data = unicode(data.encode("utf-8"), 'ascii', 'ignore')
            clear_data = unicode(clear_data.encode("utf-8"), 'ascii', 'ignore')
            description = unicode(description.encode("utf-8"), 'ascii', 'ignore')
            print('Decode finished')

            namets = self.get_timestamp()
            desc = "[%s] %s" % (auth.get_name(), description.encode("UTF-8"))

            self.save_to_file("data/backup_%s.tmp" % namets, data)
            
            shutil.copyfile('current_data/last.tmp', 'current_data/prev.tmp')
            self.save_to_file("current_data/last.tmp", data)

            os.system("""sed -e \'s/}/}\\n/g\'\;\'s/}//g\'\;\'s/{//g\' %s > tempPV.json && sed -e \'s/}/}\\n/g\'\;\'s/}//g\'\;\'s/{//g\' %s > tempNV.json && diff --suppress-common-lines -d ./tempPV.json ./tempNV.json > diff.file""" % ('current_data/last.tmp', 'current_data/prev.tmp'))

            dfle = open('diff.file', 'r')
            desc = "%s <br> %s" % (desc, dfle.read())

            self.save_to_file("current_data/clear.tmp", clear_data)
            self.save_to_file("data/description_backup_%s.tmp" % namets, desc, 'w+')

            self.save_user_rules(avaliable_for_users, namets)


        if rules:
            rules = unicode(rules.encode("utf-8"), 'ascii', 'ignore')
            self.save_to_file("data/rules_%s.tmp" % self.get_timestamp(), rules)
            self.save_to_file("current_data/rules_last.tmp", rules)

        if clientid:
            clientid = unicode(clientid.encode("utf-8"), 'ascii', 'ignore')
            self.save_to_file('current_data/clientid', clientid.strip())

        if data or clientid:
            shutil.copyfile('current_data/clear.tmp', 'current_data/out.json')

            fl = open('current_data/avaliable_ids', 'r')
            arr_ids = fl.read()
            allow = False
            arr_ids = json.loads(arr_ids)
            for some_id in arr_ids:
                if some_id['text'] == clientid:
                    allow = True
                    break

            if allow:
                start(auth, Settings, save_to_svn, desc)
                return "ok"
            else:
                return 'clientid not avaliable'


        # Main table
        r = open('current_data/last.tmp', 'r')
        data = "".join(r.readlines())

        # Rules
        rul = open('current_data/rules_last.tmp', 'r')
        rules = rul.readlines()[0]

        # ClientId
        ci = open('current_data/clientid', 'r')
        clientid = ci.read()
        ci.close()

        user_rules = self.read_user_rules()


        backups = os.listdir('data')
        filtred = {}
        for bup in backups:
            if 'backup_' in bup and bup.index('backup_') == 0:
                dt = datetime.datetime.fromtimestamp(float(bup.replace('backup_', '').replace('.tmp', '')))
                try:
                    desc = open('data/description_%s' % bup, 'r');
                    description =  desc.read();
                    desc.close();
                except IOError:
                    description = 'Description not found'

                filtred[dt.strftime("%b %d %Y %H:%M:%S")] = [bup, description]

        filtred = collections.OrderedDict(sorted(filtred.items()))
        tmpl = env.get_template('editor.html')


        return tmpl.render(
            data=data, 
            clientid=clientid.decode("UTF-8"), 
            rules=rules, 
            user_rules=user_rules,
            admin=json.dumps(auth.is_admin()),
            filtred=json.dumps(filtred),
            tool_name=Settings.name
        )


    @cherrypy.expose
    def restore(self, filename=None, remove=None):
        if filename != None and filename in os.listdir('data') and remove == None:
            return open('data/%s' % filename,'r').read()

        if filename != None and filename in os.listdir('data') and remove != None:
            os.remove('data/%s' % filename)
            os.remove('data/description_%s' % filename)
            return 'ok'


    @cherrypy.expose
    def auth(self, username=None, password=None, clientid=None):
        cherrypy.session.load()
        auth = Auth(cherrypy.session)

        if auth.is_auth() == False and username and password:
            # fed = Federation(clientid)
            ci = open('current_data/clientid', 'w')
            ci.write(clientid)
            ci.close()

            fed = Federation(clientid, Settings.federation_user_name, Settings.federation_password)

            iris = fed.load_iris()
            print(iris)
            
            if iris == False:
                return 'No response from IRIS'

            logging.debug('iris state')
            logging.debug(iris)
            try:
                data = iris.get(Settings.federation_iris_keyname)
            except urllib2.HTTPError, err:
                return "%s %s" % (err.read() , self.abutton)

            z = open('loaded_from_iris.tea', 'w+b')
            z.write(data)
            z.close()

            CryptTEA(True, 'loaded_from_iris.tea', 'encoded.json')

            enc = open('encoded.json', 'r')
            encoded = enc.read().replace('\x00', '')
            enc.close()

            enc = open('current_data/last.tmp', 'w')
            enc.write(encoded)
            enc.close()

            m = hashlib.md5()
            m.update(clientid)
            clientidmd5 = m.hexdigest()

            enc = open('current_data/last-%s.tmp' % clientidmd5, 'w')
            enc.write(encoded)
            enc.close()


            auth.auth(username, password)
            raise cherrypy.HTTPRedirect("")
        elif auth.is_auth():
            raise cherrypy.HTTPRedirect("/editor")

        tmpl = env.get_template('auth.html')
        clientid = open('current_data/clientid', 'r').read()

        fl = open('current_data/avaliable_ids', 'r')
        arr_ids = json.loads(fl.read())

        return tmpl.render(clientid=clientid, arr_ids=arr_ids, tool_name=Settings.name)

    @cherrypy.expose
    def get_backups(self):
        backups = os.listdir('data')
        filtred = {}
        for bup in backups:
            if 'backup_' in bup and bup.index('backup_') == 0:
                dt = datetime.datetime.fromtimestamp(float(bup.replace('backup_', '').replace('.tmp', '')))
                try:
                    desc = open('data/description_%s' % bup, 'r');
                    description =  desc.read();
                    desc.close();
                except IOError:
                    description = 'Description not found'

                filtred[dt.strftime("%b %d %Y %H:%M:%S")] = [bup, description]

        filtred = collections.OrderedDict(sorted(filtred.items()))
        return json.dumps(filtred)


    @cherrypy.expose
    def logout(self):
        cherrypy.session.load()
        auth = Auth(cherrypy.session)
        auth.logout()
        raise cherrypy.HTTPRedirect("/editor")


cherrypy.server.socket_host = "0.0.0.0"
cherrypy.server.socket_port = Settings.http_port

current_dir = os.path.dirname(os.path.abspath(__file__))
cherrypy.config.update({'environment': 'production',
                        'log.error_file': 'site.log',
                        'log.screen': True})
conf = {'/static': {
    'tools.staticdir.on': True,
    'tools.staticdir.dir': os.path.join(current_dir, 'static')
    }
}

# cherrypy.quickstart(TangoSettings(), '/', config=conf)


spizouzou = Daemonizer(cherrypy.engine)
spizouzou.subscribe()

cherrypy.tree.mount(TangoSettings(), '/', config=conf)
cherrypy.engine.start()
cherrypy.engine.block()

